﻿#ifndef StateMachine_h__
#define StateMachine_h__

/********************************************************************
	创建于:		2011/04/04
	创建于:		4:4:2011   14:29
	基本文件:	StateMachine
	文件扩展:	h
	作者:		王凯
	
	目的:		状态机类。提供对从State继承而来的状态的集中管理。
*********************************************************************/

#include <cassert>
#include <string>
#include "Messaging/Telegram.h"
#include "State.h"

template<typename entity_type>
class StateMachine
{
private:
	//状态机的持有对象
	entity_type* m_pOwner;

	//当前的状态指针
	State<entity_type>* m_pCurrentState;

	//前一个状态的指针
	State<entity_type>* m_PreviousState;

	//全局状态指针
	State<entity_type>* m_pGlobalState;
public:

	StateMachine(entity_type* owner):
	  m_pOwner(owner),
		  m_pCurrentState(NULL),
		  m_PreviousState(NULL),
		  m_pGlobalState(NULL){}

	  virtual ~StateMachine(){}

	  void SetCurrentState(State<entity_type>* ps){ m_pCurrentState = ps;}
	  void SetPreviousState(State<entity_type>* ps){ m_PreviousState = ps;}
	  void SetGlobalState(State<entity_type>* ps){ m_pGlobalState = ps;}

	  void Update()const
	  {
		  if(m_pGlobalState) m_pGlobalState->Execute(m_pOwner);

		  if(m_pCurrentState) m_pCurrentState->Execute(m_pOwner);
	  }

	  bool HandleMessage(const Telegram& msg)const
	  {
		  //让当前状态接受消息，成功则返回真
		  if(m_pCurrentState && m_pCurrentState->OnMessage(m_pOwner, msg))
			  return true;

		  //如果当前状态不能接受消息，则尝试全局状态，成功则返回真
		  if(m_pGlobalState && m_pGlobalState->OnMessage(m_pOwner, msg))
			  return true;

		  //看来是失败了
		  return false;
	  }

	  void ChangeState(State<entity_type>* ps)
	  {
		  assert(ps &&"<StateMachie::ChangeState> 正在尝试将空状态指针赋值给当前状态");

		  m_PreviousState = m_pCurrentState;

		  m_pCurrentState->Exit(m_pOwner);

		  m_pCurrentState = ps;

		  m_pCurrentState->Enter(m_pOwner);
	  }

	  void RevertToPreviousState()
	  {
		  ChangeState(m_PreviousState);
	  }

	  bool isInState(const State<entity_type>& st)const
	  {
		  if(typeid(*m_pCurrentState) == typeid(st)) return true;
		  return false;
	  }

	  State<entity_type>* CurrentState(){ return m_pCurrentState;}
	  State<entity_type>* PreviousState(){ return m_PreviousState;}
	  State<entity_type>* GlobalState(){ return m_pGlobalState;}

	  std::string GetNameOfCurrentState()
	  {
		  std::string s(typeid(*m_pCurrentState).name());

		  //把class从名字中移除
		  if(s.size() > 5)
			  s.erase(0,6);

		  return s;
	  }
};

#endif // StateMachine_h__